package com.cloud.lucene;

import com.cloud.lucene.domain.Sku;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = LuceneApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("dev")
@Slf4j
public class LuceneTest2 {

    @Test
    public void testCreateIndex() throws IOException {
        Sku sku1=new Sku("id1","SkuName1",1,2,"图片1","categoryName1","品牌1","1",1);
        List<Sku> skuList = new ArrayList<>();
        skuList.add(sku1);
        //2. 创建文档对象
        List<Document> documentList = new ArrayList<>(skuList.size());
        for (Sku sku : skuList) {
            Document document = new Document();

            /**
             * 是否分词：否，分词没有意义
             * 是否索引：是，为了查询
             * 是否存储：是，为了去真实存储地方拿到所有数据
             * 下面的字段都按照以上3个方面分析
             */
            document.add(new StringField("id", sku.getId(), Field.Store.YES));
            /**
             * 是否分词：是，关键词搜索
             * 是否索引：是，为了查询
             * 是否存储：是，为了显示
             */
            document.add(new TextField("name", sku.getName(), Field.Store.YES));
            /**
             * 是否分词：是，底层算法决定
             * 是否索引：是，为了范围查询
             * 是否存储：是，为了显示
             */
            document.add(new IntPoint("price", sku.getPrice()));
            document.add(new StoredField("price", sku.getPrice()));
            /**
             * 是否分词：否，品牌名是一个整体
             * 是否索引：是，为了查询
             * 是否存储：是，为了显示
             */
            document.add(new StringField("brandName", sku.getBrandName(), Field.Store.YES));
            /**
             * 是否分词：同上
             * 是否索引：
             * 是否存储：
             */
            document.add(new StringField("categoryName", sku.getCategoryName(), Field.Store.YES));
            /**
             * 是否分词：否，没有意义
             * 是否索引：否，不查询
             * 是否存储：是，为了显示
             */
            document.add(new StoredField("image", sku.getImage()));

            documentList.add(document);
        }
        //3. 创建分词器, 对英文分词支持很好，对中文是一个字分词
        Analyzer analyzer = new StandardAnalyzer();
        //4. 创建Directory目录对象，目录对象表示索引库的位置
        Directory directory = FSDirectory.open(Paths.get("F:\\luceneDir"));
        //5. 创建IndexWriterConfig对象，这个对象中指定切分词所用的分词器
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        //6. 创建IndexWriter输出流对象，指定输出的位置和使用的config初始化对象
        IndexWriter writer = new IndexWriter(directory, config);
        //7. 写入文档到索引库
        for (Document document : documentList) {
            writer.addDocument(document);
        }
        //8. 释放资源
        writer.close();
    }

    @Test
    public void testUpdate() throws Exception {
        Document document = new Document();


        document.add(new StringField("id", "123", Field.Store.YES));

        document.add(new TextField("name", "改名", Field.Store.YES));

        document.add(new IntPoint("price", 123));
        document.add(new StoredField("price", 123));

        document.add(new StringField("brandName", "改名", Field.Store.YES));

        document.add(new StringField("categoryName", "改名", Field.Store.YES));

        document.add(new StoredField("image", "xxx.jpg"));

        //3. 创建分词器, 对英文分词支持很好，对中文是一个字分词
        Analyzer analyzer = new StandardAnalyzer();
        //4. 创建Directory目录对象，目录对象表示索引库的位置
        Directory directory = FSDirectory.open(Paths.get("G:\\luceneDir"));
        //5. 创建IndexWriterConfig对象，这个对象中指定切分词所用的分词器
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        //6. 创建IndexWriter输出流对象，指定输出的位置和使用的config初始化对象
        IndexWriter writer = new IndexWriter(directory, config);
        //7. 写入文档到索引库
        writer.updateDocument(new Term("id", "1191945635377582080"), document);
        //8. 释放资源
        writer.close();
    }

    @Test
    public void testDelete() throws Exception {
        //3. 创建分词器, 对英文分词支持很好，对中文是一个字分词
        Analyzer analyzer = new StandardAnalyzer();
        //4. 创建Directory目录对象，目录对象表示索引库的位置
        Directory directory = FSDirectory.open(Paths.get("G:\\luceneDir"));
        //5. 创建IndexWriterConfig对象，这个对象中指定切分词所用的分词器
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        //6. 创建IndexWriter输出流对象，指定输出的位置和使用的config初始化对象
        IndexWriter writer = new IndexWriter(directory, config);
        //7. 写入文档到索引库
        //writer.deleteDocuments(new Term("id", "123"));
        long l = writer.deleteAll();
        //8. 释放资源
        writer.close();
    }



    @Test
    public void testSearch() throws Exception {
        // 1. 创建Query搜索对象
        Analyzer analyzer = new StandardAnalyzer();

        QueryParser queryParser = new QueryParser("name", analyzer);
        Query query = queryParser.parse("brandName:品牌1");
        // 2. 创建Directory流对象，声明索引库位置
        Directory directory = FSDirectory.open(Paths.get("F:\\luceneDir"));

        // 3. 创建索引读取对象
        IndexReader reader = DirectoryReader.open(directory);

        // 4. 创建索引搜索对象
        IndexSearcher indexSearcher = new IndexSearcher(reader);

        // 5. 执行搜索，获取结果集
        TopDocs result = indexSearcher.search(query, 10);
        System.out.println("-----符合条件的总结果数：" + result.totalHits);

        // 6. 解析结果集
        ScoreDoc[] scoreDocs = result.scoreDocs;
        for (ScoreDoc scoreDoc : scoreDocs) {
            // 文档ID
            int docId = scoreDoc.doc;

            Document doc = indexSearcher.doc(docId);
            System.out.println("==========================");
            System.out.println(scoreDoc);
            System.out.println("id:" + doc.get("id"));
            System.out.println("name:" + doc.get("name"));
            System.out.println("price:" + doc.get("price"));
            System.out.println("image:" + doc.get("image"));
            System.out.println("brandName:" + doc.get("brandName"));
            System.out.println("categoryName:" + doc.get("categoryName"));
        }
    }
}
